/*
 * Created on 08/01/2013 - 2:24 PM
 */
package sembr.vtk.animation;

import vtk.*;

/**
 *
 * @author adriano
 */
public class VtkMovie3D
{   
    private String path; 
    private String dimension;
    private int nrOfFrames;
    private int startTime;
    private int timeStep;
    private String fieldComponent;
    private vtkPNGReader[] readerCollection; 
    private vtkPlane cutPlane;
    private vtkPlaneCollection planeCollection;
    private vtkCutter[] cutterCollection;
    private vtkDataSetMapper[] dataSetMapper;
    private vtkPolyDataMapper[] polyDataMapper;
    private vtkScalarBarActor barActor;
    private vtkActorCollection actorFieldCollection;
    private vtkActorCollection actorPlaneCollection;
    private vtkCanvas panel;
    
    public VtkMovie3D(String path, String dimension, int nrOfFrames, int startTime, int timeStep, double[] planeOrign, double[] planeNormal, String fieldComponent)
    {
       LoadVTKLibraries();
       setPath(path);
       setDimension(dimension);
       setNrOfFrames(nrOfFrames); 
       setStartTime(startTime);
       setTimeStep(timeStep);
       setFieldComponent(fieldComponent);
       setReaderCollection(new vtkPNGReader[nrOfFrames]);
       setCutPlane(new vtkPlane(), planeOrign, planeNormal);
       setPlaneCollection(new vtkPlaneCollection());
       setCutterCollection(new vtkCutter[nrOfFrames]);
       setDataSetMapper(new vtkDataSetMapper[nrOfFrames]);
       setPolyDataMapper(new vtkPolyDataMapper[nrOfFrames]);
       setActorFieldCollection(new vtkActorCollection());
       setActorPlaneCollection(new vtkActorCollection());
       createScene();
       setBarLegend(new vtkScalarBarActor());
       //setPanel(new vtkCanvas());
    }
    
    public VtkMovie3D(String path, String dimension, String fieldComponent, int nrOfFrames, double[] planeOrign, double[] planeNormal)
    {
       LoadVTKLibraries();
       setPath(path);
       setDimension(dimension);
       setNrOfFrames(nrOfFrames); 
       setFieldComponent(fieldComponent);
       setReaderCollection(readerCollection);
       setCutPlane(new vtkPlane(), planeOrign, planeNormal);
       setPlaneCollection(new vtkPlaneCollection());
       setCutterCollection(new vtkCutter[nrOfFrames]);
       setDataSetMapper(new vtkDataSetMapper[nrOfFrames]);
       setPolyDataMapper(new vtkPolyDataMapper[nrOfFrames]);
       setActorFieldCollection(new vtkActorCollection());
       setActorPlaneCollection(new vtkActorCollection());       
       createScene();
       //setPanel(new vtkCanvas());
    }  
    
    /**
     * @return the path
     */
    public String getPath() 
    {
        return path;
    }
    
    /**
     * @return the dimension
     */
    public String getDimension() 
    {
        return dimension;
    }
    
    /**
     * @return the nrOfFrames
     */
    public int getNrOfFrames() 
    {
        return nrOfFrames;
    }
    
    /**
     * @return the startTime
     */
    public int getStartTime() 
    {
        return startTime;
    }  
    
    /**
     * @return the timeStep
     */
    public int getTimeStep() 
    {
        return timeStep;
    }
    
    /**
     * @return the readerCollection
     */
    public vtkPNGReader[] getReaderCollection() 
    {
        return readerCollection;
    }
    
     /**
     * @return the cutPlane
     */
    public vtkPlane getCutPlane() 
    {
        return this.cutPlane;
    }
    
    public vtkPlaneCollection getPlaneCollection()
    {
        return planeCollection;
    }
    
    /**
     * @return the cutterCollection
     */
    public vtkCutter[] getCutterCollection() 
    {
        return cutterCollection;
    }
    
    /**
     * @return the dataSetMapper
     */
    public vtkDataSetMapper[] getDataSetMapper() 
    {
        return dataSetMapper;
    }
     
    /**
     * @return the polyDataMapper
     */
    public vtkPolyDataMapper[] getPolyDataMapper() 
    {
        return polyDataMapper;
    }
    
    /**
     * @return the actorFieldCollection
     */
    public vtkActorCollection getActorFieldCollection() 
    {
        return actorFieldCollection;
    }
    
    /**
     * @return the actorPlaneCollection
     */
    public vtkActorCollection getActorPlaneCollection() 
    {
        return actorPlaneCollection;
    }
    
    /**
     * @return the barActor
     */
    public vtkScalarBarActor getBarActor()
    {
        return barActor;
    }
    
    /**
     * @return the panel
     */
    public vtkCanvas getPanel() 
    {
        return panel;
    }
        
    /**
     * @param path the path to set
     */
    private void setPath(String path) 
    {
        this.path = path;
    }
    
    /**
     * @param dimension the dimension to set
     */
    private void setDimension(String dimension) 
    {
        this.dimension = dimension;
    }
    
    /**
     * @param nrOfFrames the nrOfFrames to set
     */
    private void setNrOfFrames(int nrOfFrames) 
    {
        this.nrOfFrames = nrOfFrames;
    }
        
    /**
     * @param startTime the startTime to set
     */
    private void setStartTime(int startTime) 
    {
        this.startTime = startTime;
    }
    
    /**
     * @param timeStep the timeStep to set
     */
    private void setTimeStep(int timeStep) 
    {
        this.timeStep = timeStep;
    }
    
    /**
     * @return the fieldComponent
     */
    public String getFieldComponent() 
    {
        return fieldComponent;
    }

    /**
     * @param fieldComponent the fieldComponent to set
     */
    private void setFieldComponent(String fieldComponent) 
    {
        this.fieldComponent = fieldComponent;
    }
        
    /**
     * @param readerCollection the readerCollection to set
     */
    private void setReaderCollection(vtkPNGReader[] readerCollection) 
    {
        this.readerCollection = readerCollection;
    }
    
    /**
     * @param cutPlane the cutPlane to set
     */
    private void setCutPlane(vtkPlane cutPlane, double[] origin, double[] normal) 
    {
        this.cutPlane = cutPlane; 
        
        double[] tempOrigin = {255, 0, 0};
        double[] tempNormal = {-3.476, -3.3, 0.};
        
        if (origin == null)
            this.cutPlane.SetOrigin(tempOrigin);
        else      
            this.cutPlane.SetOrigin(origin);
        
        if (normal == null)
            this.cutPlane.SetNormal(tempNormal);
        else
            this.cutPlane.SetNormal(normal);
    }
    
    /**
     * @param planeCollection the planeCollection to set
     */
    
    private void setPlaneCollection(vtkPlaneCollection planeCollection)
    {       
        this.planeCollection = planeCollection;
        this.planeCollection.AddItem(cutPlane);
    }

    /**
     * @param cutterCollection the cutterCollection to set
     */
    private void setCutterCollection(vtkCutter[] cutterCollection) 
    {
        this.cutterCollection = cutterCollection;
    }
        
    /**
     * @param dataSetMapper the dataSetMapper to set
     */
    private void setDataSetMapper(vtkDataSetMapper[] dataSetMapper) 
    {
        this.dataSetMapper = dataSetMapper;
    }
    
    /**
     * @param polyDataMapper the polyDataMapper to set
     */
    private void setPolyDataMapper(vtkPolyDataMapper[] polyDataMapper) 
    {
        this.polyDataMapper = polyDataMapper;
    }
    
    private void setBarLegend(vtkScalarBarActor barActor)
    {   
        this.barActor = barActor;
        this.barActor.SetLookupTable(getDataSetMapper()[0].GetLookupTable());
        this.barActor.GetTitleTextProperty().BoldOff();
        this.barActor.SetTitle(getFieldComponent());        
        this.barActor.SetNumberOfLabels(6);
        this.barActor.SetWidth(0.06);
        this.barActor.SetHeight(0.83);    
    }
    
    /**
     * @param actorFieldCollection the actorFieldCollection to set
     */
    private void setActorFieldCollection(vtkActorCollection actorFieldCollection) 
    {
        this.actorFieldCollection = actorFieldCollection;
    }
    
     /**
     * @param actorPlaneCollection the actorPlaneCollection to set
     */
    private void setActorPlaneCollection(vtkActorCollection actorPlaneCollection) 
    {
        this.actorPlaneCollection = actorPlaneCollection;
    }
    
    /**
     * @param panel the panel to set
     */
    private void setPanel(vtkCanvas panel) 
    {
        this.panel = panel;       
    }
                  
    /**
     * createScene method will create the network beetween vtk data objects and process 
     */   
    private void createScene() 
    {       
        String prefix = getPath() + "sembr.dxf.presentation/simulation/images/movie3D/" + getFieldComponent() + "-000000.00." + getDimension();
        
        for (int i = 0; i < getNrOfFrames(); i++)
        {
             // reader settings
            getReaderCollection()[i] = new vtkPNGReader(); 
            getReaderCollection()[i].SetFilePrefix(prefix);           
            getReaderCollection()[i].SetDataByteOrderToBigEndian();
            getReaderCollection()[i].SetDataExtent(0, 269, 0, 269, 30, 59);
            getReaderCollection()[i].SetFilePattern("%s%02d" + ".t" + String.valueOf(getStartTime() + (i * getTimeStep())) + ".png");
            getReaderCollection()[i].Update();
              
            // cutting plane settings
            getCutterCollection()[i] = new vtkCutter();
            getCutterCollection()[i].SetInput(getReaderCollection()[i].GetOutput());
            getCutterCollection()[i].SetCutFunction(getCutPlane());
              
            // mapper settings for reader output dataset
            getDataSetMapper()[i] = new vtkDataSetMapper();
            getDataSetMapper()[i].SetInput(getReaderCollection()[i].GetOutput());
            getDataSetMapper()[i].SetClippingPlanes(getPlaneCollection());
            getDataSetMapper()[i].Update();
            //getDataSetMapper()[i].ImmediateModeRenderingOn();
                       
            // mapper settings for cutting plane output dataset
            getPolyDataMapper()[i] = new vtkPolyDataMapper();
            getPolyDataMapper()[i].SetInputConnection(getCutterCollection()[i].GetOutputPort());
            getPolyDataMapper()[i].SetScalarRange(getReaderCollection()[i].GetOutput().GetPointData().GetScalars().GetRange());
            //getPolyDataMapper()[i].ImmediateModeRenderingOn();   
            
            // cut object actor
            vtkActor actor = new vtkActor();
            actor.SetMapper(getDataSetMapper()[i]);
            actor.SetVisibility(0);
                       
            // cutting plane actor
            vtkActor actor2 = new vtkActor();
            actor2.SetMapper(getPolyDataMapper()[i]);
            actor2.SetVisibility(0);  
            
            // add the two actors to collection
            getActorFieldCollection().AddItem(actor);            
            getActorPlaneCollection().AddItem(actor2);  
        }
        
//        // just a test to see the rendering actor
//        vtkActor actora = ((vtkActor)getActorFieldCollection().GetItemAsObject(10));
//        vtkActor actorb = ((vtkActor)getActorPlaneCollection().GetItemAsObject(10));        
//        //actora.RotateY(180.);
//        actora.SetVisibility(1);
//        actorb.SetVisibility(1);
//        //actora.RotateY(180.);
//        //actorb.RotateY(180.);
//        getPanel().GetRenderer().AddActor(actora); 
//        getPanel().GetRenderer().AddActor(actorb);
//        
//        vtkTransform transformation = new vtkTransform();
//        //transformation.PostMultiply();
//        transformation.RotateY(180.);
//        //transformation.Update();        
//        getPanel().GetRenderer().GetActiveCamera().ApplyTransform(transformation);
//        getPanel().GetRenderer().ResetCamera();
//        getPanel().GetRenderer().SetBackground(0., 0., 0.);   
    }
       
    private static void LoadVTKLibraries()
    {
        System.loadLibrary("vtkCommon");
        System.loadLibrary("vtkFiltering");
        System.loadLibrary("vtkGenericFiltering");
        System.loadLibrary("vtkGraphics");
        System.loadLibrary("vtkImaging");
        System.loadLibrary("vtksys");
        System.loadLibrary("vtkexpat");
        System.loadLibrary("vtkfreetype");
        System.loadLibrary("vtkftgl");
        System.loadLibrary("vtkzlib");
        System.loadLibrary("vtktiff");
        System.loadLibrary("vtkpng");
        System.loadLibrary("vtkIO");
        System.loadLibrary("vtkRendering");
        System.loadLibrary("vtkVolumeRendering");
        System.loadLibrary("vtkCommonJava");
        System.loadLibrary("vtkFilteringJava");
        System.loadLibrary("vtkGenericFilteringJava");
        System.loadLibrary("vtkGraphicsJava");
        System.loadLibrary("vtkHybridJava");
        System.loadLibrary("vtkImagingJava");
        System.loadLibrary("vtkIOJava");
        System.loadLibrary("vtkGraphicsJava");
        System.loadLibrary("vtkRenderingJava");
    }
}
